package com.mt.mall.service.User.impl;

import com.mt.common.core.security.RedisUtil;
import com.mt.mall.dao.User.ShippingAddressDao;

import com.mt.common.core.exception.BusinessException;
import com.mt.common.core.web.base.PageDTO;
import com.mt.common.core.web.base.PageResultDTO;
import com.mt.common.core.web.base.BaseEntity;
import com.mt.common.core.web.BaseService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mt.mall.entity.User.ShippingAddress;
import com.mt.mall.service.User.ShippingAddressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@Transactional
public class ShippingAddressServiceBean extends BaseService implements ShippingAddressService {

    private static Logger logger = LogManager.getLogger();

	@Autowired
	private ShippingAddressDao shippingAddressDao;

	@Resource
	private RedisTemplate<String, List<ShippingAddress>> redisTemplate;

	@Autowired
	StringRedisTemplate stringRedisTemplate;


	@Autowired
	private RedisUtil redisUtil;


	/**
	 * 根据分页参数查询收获地址集合
	 *
	 * @param pageDTO 分页条件
	 */
	@Override
	public PageResultDTO findShippingAddresss(PageDTO pageDTO){
        pageDTO.setStartIndex((pageDTO.getCurrentPage()-1)*pageDTO.getPageSize());
		//TODO:请在此校验参数的合法性
		this.validateFindShippingAddresss(pageDTO);
		List<ShippingAddress> shippingAddressDTOS = this.shippingAddressDao.findShippingAddresss(pageDTO);
		Long totalCount = this.shippingAddressDao.findShippingAddressTotalCount(pageDTO);

		PageResultDTO pageResultDTO = new PageResultDTO();
		pageResultDTO.setTotalCount(totalCount);
		pageResultDTO.setDatas(shippingAddressDTOS);

		return pageResultDTO;
	}

	/**
	 * 查询全部收获地址集合
	 *
	 */
	@Override
	public List<ShippingAddress> findAllShippingAddresss(){
		return this.shippingAddressDao.findAllShippingAddresss();
	}

	/**
	 * 查询所有收获地址集合(只提取ID 和 Name)
	 *
	 */
	@Override
	public List<ShippingAddress> findAllShippingAddresssWithIdName(){
		//TODO:请在此校验参数的合法性
		this.validateFindAllShippingAddresssWithIdName();
		return this.shippingAddressDao.findAllShippingAddresssWithIdName();
	}

	/**
	 * 根据名称查询收获地址集合(只提取ID 和 Name)
	 *
	 * @param shippingAddressName 名称
	 */
	@Override
	public List<ShippingAddress> findShippingAddresssWithIdNameByName(String shippingAddressName){
		//TODO:请在此校验参数的合法性
		this.validateFindShippingAddresssWithIdNameByName(shippingAddressName);
		//TODO:缓存取对应参数
		Set<String> keys = stringRedisTemplate.keys("searchData:ShippingAddress_where_shippingAddressName_" + shippingAddressName);
		List<ShippingAddress> shippingAddresss = new ArrayList<>();
		if (keys.isEmpty()) {
		shippingAddresss = this.shippingAddressDao.findShippingAddresssWithIdNameByName(shippingAddressName);
		redisTemplate.opsForValue().set("searchData:ShippingAddress_where_shippingAddressName_" + shippingAddressName, shippingAddresss, 30, TimeUnit.DAYS);
		} else {
		shippingAddresss = redisTemplate.opsForValue().get("searchData:ShippingAddress_where_shippingAddressName_" + shippingAddressName);
		}
		return shippingAddresss;
	}

	/**
	 * 根据ID查询指定的收获地址(只提取ID 和 Name)
	 *
	 * @param shippingAddressId Id
	 */
	@Override
	public ShippingAddress findShippingAddresssWithIdNameById(Long shippingAddressId){
		//TODO:请在此校验参数的合法性
		this.validateFindShippingAddresssWithIdNameById(shippingAddressId);
		return this.shippingAddressDao.findShippingAddresssWithIdNameById(shippingAddressId);
	}

	/**
	 * 根据ID查询指定的收获地址
	 *
	 * @param shippingAddressId Id
	 */
	@Override
	public ShippingAddress findShippingAddress(Long shippingAddressId){
		//TODO:请在此校验参数的合法性
		this.validateFindShippingAddress(shippingAddressId);
		return this.shippingAddressDao.findShippingAddress(shippingAddressId);
	}

	/**
	 * 根据ID查询指定的收获地址(包含外键)
	 *
	 * @param shippingAddressId Id
	 */
	@Override
	public ShippingAddress findShippingAddressWithForeignName(Long shippingAddressId){
		//TODO:请在此校验参数的合法性
		this.validateFindShippingAddressWithForeignName(shippingAddressId);
		return this.shippingAddressDao.findShippingAddressWithForeignName(shippingAddressId);
	}

	/**
	 * 新增收获地址
	 *
	 * @param shippingAddress 实体对象
	 */
	@Override
	public ShippingAddress saveShippingAddress(ShippingAddress shippingAddress){
		//TODO:请在此校验参数的合法性
		this.validateSaveShippingAddress(shippingAddress);
		//TODO:填充公共参数
		this.setSavePulicColumns(shippingAddress);
		Long rows = this.shippingAddressDao.saveShippingAddress(shippingAddress);
		if(rows != 1)
		{
			String error = "新增保存收获地址出错，数据库应该返回1,但返回了 "+rows;
			throw new BusinessException(error);
		}
		return shippingAddress;
	}

	/**
	 * 更新收获地址
	 *
	 * @param shippingAddress 实体对象
	 */
	@Override
	public ShippingAddress updateShippingAddress(ShippingAddress shippingAddress){
		//TODO:请在此校验参数的合法性
		this.validateUpdateShippingAddress(shippingAddress);
		Long rows = this.shippingAddressDao.updateShippingAddress(shippingAddress);
		if(rows != 1)
		{
			String error = "修改保存收获地址出错，数据库应该返回1,但返回了 "+rows+",数据可能被删除";
			throw new BusinessException(error);
		}
		return shippingAddress;
	}

	/**
	 * 根据ID删除收获地址
	 *
	 * @param shippingAddressId ID
	 */
	@Override
	public void deleteShippingAddress(Long shippingAddressId){
		//TODO:请在此校验参数的合法性
		this.validateDeleteShippingAddress(shippingAddressId);

		Map<Class<? extends BaseEntity>,EntityUsage> entityUsageMap = this.checkForeignEntity(ShippingAddress.class, shippingAddressId);
		if(entityUsageMap != null && entityUsageMap.size() >0){
			StringBuilder errors = new StringBuilder();
			errors.append("计划删除的数据正在被以下数引用\n");
			for(EntityUsage entityUsage : entityUsageMap.values()){
				errors.append("\t").append(entityUsage.getEntityLabel()).append("\n");
				for(Map.Entry<Long,String> entry : entityUsage.getUsageIdNames().entrySet() ){
					errors.append("\t\t").append(entry.getKey()).append("\t").append(entry.getValue()).append("\n");
				}
			}
			errors.append("，不能删除，请检查处理后再删除");
			throw  new BusinessException(errors.toString());
		}

		Long rows = this.shippingAddressDao.deleteShippingAddress(shippingAddressId);
		if(rows != 1){
			String error = "删除收获地址出错，数据可能已经被删除";
			throw new BusinessException(error);
		}
	}

	@Override
	public List<ShippingAddress> findShippingAddressByUserId(Long userId) {
		return this.shippingAddressDao.findShippingAddressByUserId(userId);
	}

	@Override
	public void setDefaultAddress(ShippingAddress shippingAddress) {
		this.shippingAddressDao.setDefaultAddress(shippingAddress);
		String USER_DEFAULT_ADDRESS=shippingAddress.getUserId()+"-"+"DEFAULT_ADDRESS";
		//更新默认地址删除缓存
		redisUtil.del(USER_DEFAULT_ADDRESS);
	}

	@Override
	public ShippingAddress getDefaultAddress() {
		Long userId = this.getLoginUserId();
		String USER_DEFAULT_ADDRESS=userId+"-"+"DEFAULT_ADDRESS";
		ShippingAddress shippingAddress = (ShippingAddress) redisUtil.get(USER_DEFAULT_ADDRESS);
		//首先从Redis中获取默认收获地址，获取不到则数据库中查询并缓存入Redis
		if(shippingAddress==null){
			shippingAddress = this.shippingAddressDao.getDefaultAddress(userId);
			//缓存入Reids，有效期为1天
			redisUtil.set(USER_DEFAULT_ADDRESS,shippingAddress,60*60*24);
		}
		return shippingAddress;
	}

	//TODO:---------------验证-------------------

	private void validateFindShippingAddresss(PageDTO pageDTO) {
	//TODO:请使用下面方法添加数据过滤条件
	//		pageDTO.addFilter("creatorId",this.getLoginUserId());
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}

	private void validateFindShippingAddresssWithIdNameByName(String shippingAddressName) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}


	private void validateFindAllShippingAddresssWithIdName() {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}

	private void validateFindShippingAddresssWithIdNameById(Long shippingAddressId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}

	private void validateFindShippingAddress(Long shippingAddressId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}

	private void validateFindShippingAddressWithForeignName(Long shippingAddressId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}

	private void validateSaveShippingAddress(ShippingAddress shippingAddress) {
	//不为空判断
	if (shippingAddress.getEid() != null || shippingAddress.getCreatorId() != null || shippingAddress.getCreateDatetime() != null) {
	throw new BusinessException("非法请求");
	}
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}

	private void validateUpdateShippingAddress(ShippingAddress shippingAddress) {
	//不为空判断
	if (shippingAddress.getEid() == null) {
	throw new BusinessException("唯一标识不能为空");
	}
	//是否存在判断
	if (this.shippingAddressDao.findShippingAddressTotalCount(PageDTO.create(ShippingAddress.FIELD_ID, shippingAddress.getEid())) == 0) {
	throw new BusinessException("修改的收获地址 " + shippingAddress.getName() + " 不存在，修改失败，请重试或联系管理员");
	}
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}

	private void validateDeleteShippingAddress(Long shippingAddressId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateShippingAddress()写法
	}

	@Override
	public boolean canDownloadAttachment(String formName, Long id) {
	return true;
	}
}
